package com.jellyfishumbrella.GL;

import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.util.ArrayList;
import java.util.LinkedList;

import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;

//import com.jellyfishumbrella.GL.Primitives.Grid;

public abstract class AbstractGameLogic {
	public static final int						TICK_MILLIS			= 100;
	public static long							tickTime			= 0;
	public static int							refreshRate			= 600;
	public static float							GL_SCALE			= 1.0f / 100.0f;
	public static Boolean						gameRunning			= true;
	public static long							startTime			= 0;
	public long									lastLoopTime		= getTime();
	protected long								lastFpsTime			= getTime() + 60;
	protected int								fps					= 60;
	protected static long						timerTicksPerSecond	= Sys.getTimerResolution();
	protected boolean							lastMouseDown		= false;

//	public static Grid							grid;
	public static RendererGL					renderGL;
	public static Animator						animator;

	public static OctreeNode					octree;

	protected static AbstractKeyboardMouse		keyboardMouseThread;
	protected static QThread					qThread;

	public static ArrayList<ThreadLoop>			allThreads;

	public static LinkedList<AbstractActivity>	activityQ			= new LinkedList<AbstractActivity>();

	public AbstractGameLogic(AbstractKeyboardMouse keys) {
		startTime = getTime();
		allThreads = new ArrayList<ThreadLoop>();

		keyboardMouseThread = keys;
		allThreads.add(keyboardMouseThread);
		
		qThread = new QThread("qThread");
		qThread.sleepMillis = TICK_MILLIS;
		allThreads.add(qThread);
		
		for(ThreadLoop currThread : allThreads){
			currThread.start();
		}

		// createOctree();
	}

	public void shutdown() {
		System.out.println("shutdown");

		for (ThreadLoop currThread : allThreads) {
			currThread.done = true;
		}
	}

	public void createOctree() {
		octree = new OctreeNode(null, new Vector3d(-1000, 1000, -1000), new Vector3d(1000, -1000, 1000));
	}

	public void createGrid() {

//		grid = new Grid(1000, 1000, 10);

//		renderGL.add(grid);
		// octree.add(grid);
	}

	/**
	 * Get the high resolution time in milliseconds
	 * 
	 * @return The high resolution time in milliseconds
	 */
	public static long getTime() {
		// we get the "timer ticks" from the high resolution timer
		// multiply by 1000 so our end result is in milliseconds
		// then divide by the number of ticks in a second giving
		// us a nice clear time in milliseconds
		return ((Sys.getTime() * 1000) / timerTicksPerSecond) - startTime;
	}

	public static void getRefreshRate() {
		int refreshRate = 60;
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		GraphicsDevice[] gs = ge.getScreenDevices();

		// for (int i = 0; i < gs.length; i++) {
		DisplayMode dm = gs[0].getDisplayMode();

		// Get refresh rate in Hz
		refreshRate = dm.getRefreshRate();
		if (refreshRate == DisplayMode.REFRESH_RATE_UNKNOWN) {
			// Unknown rate
		}

		// Get number of colors
		int bitDepth = dm.getBitDepth();
		if (bitDepth == DisplayMode.BIT_DEPTH_MULTI) {
			// Multiple bit depths are supported in this display mode
		} else {
			int numColors = (int) Math.pow(2, bitDepth);
		}
		// }
		// return refreshRate;
	}

	public void gameLoop() {
		long currTime;
		while (gameRunning) {
			// Game Logic
			gameLogic();
			keyboardMouseThread.doProcess = true;
			qThread.doProcess = true;

			// Game Rendering
			renderGL.render();

			// update window contents
			Display.update();
		}
	}

	public void update(long currTime) {
		// long newTickTime = currTime % TICK_MILLIS;
		// if (newTickTime < tickTime) {
		// System.out.println("tick: " + newTickTime);
		// processActivityQ(TICK_MILLIS - newTickTime);
		// }
		animator.animateAll(currTime);
	}

	public abstract void init();

	public abstract void gameLogic();

	public class QThread extends ThreadLoop {

		public QThread(String name){
			super(name);
		}
		
		@Override
		public void process() {
			//long startTime = getTime();
			//long timeTaken = 0;
			
			//while (timeTaken < TICK_MILLIS) {
				AbstractActivity currActivity = activityQ.pollFirst();
				if (currActivity != null) {
					currActivity.process();
				}

			//	timeTaken += getTime() - startTime;
			//}
		}
	}
}
